package com.cictec.middleware.gps.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cictec.middleware.commons.cache.ecache.EHCacheUtils;
import com.cictec.middleware.commons.utils.ZoneUtils;
import com.cictec.middleware.commons.utils.gps.GpsUtils;
import com.cictec.middleware.core.entity.BusLineMapPoint;
import com.cictec.middleware.core.entity.BusLineStation;
import com.cictec.middleware.core.exception.BusLineMapPointException;
import com.cictec.middleware.gps.service.feign.MiddlewareDcFeignClient;
import com.vividsolutions.jts.geom.Geometry;

/**
 * 线路信息-线路地图service
 * @author ql
 *
 */
@Service
public class BusLineMapPointService {

	public static Logger logger = LoggerFactory.getLogger(BusLineMapPointService.class);

	private double maxOffLine = 100;
	
	
	public Map<String, Geometry> initLineMapPointGeometry(Map<String, List<BusLineMapPoint>> busLineMapPointMap) {
		// TODO Auto-generated method stub
		Map<String, Geometry> map = new HashMap<String, Geometry>();
		for (String lineType : busLineMapPointMap.keySet()) {
			map.put(lineType, ZoneUtils.createLineStringGeometry(busLineMapPointMap.get(lineType)));
		}
		return map;
		
	}
	
	
	
	/**
	 * 【缓存】获取线路地图线路站点线路，两个站点之间的地图线段(包括两个端点)
	 * @throws BusLineMapPointException 
	 */
	public List<BusLineMapPoint> getBusLineMapPoint(List<BusLineMapPoint> busLinePoints, int startStationSequence, int endStationSequence){
		
		List<BusLineMapPoint> rtList = new ArrayList<BusLineMapPoint>();
		
		BusLineMapPoint startMapPoint = getBusLineMapPoint(busLinePoints, startStationSequence);
		BusLineMapPoint endMapPoint = getBusLineMapPoint(busLinePoints, endStationSequence);
		
		if(startMapPoint == null || endMapPoint == null){
//			throw new BusLineMapPointException(PMSUtils.format("找不到lineUuid:{} lineType:{} 站点序号:{} 对于线路地图上的点", lineUuid, lineType, endStationSequence));
		}
		
		try {
			rtList = busLinePoints.subList(busLinePoints.indexOf(startMapPoint), busLinePoints.indexOf(endMapPoint) + 1);
		} catch (Exception e) {
//			e.printStackTrace();
		}
		
		return rtList;
	}
	
	/**
	 * 【缓存】根据站点序号，获取地图线段站点坐标,没有（找不到）返回null
	 * @param list
	 * @param stationSequence
	 * @return
	 */
	public BusLineMapPoint getBusLineMapPoint(List<BusLineMapPoint> list, int stationSequence){
		
		for(BusLineMapPoint mapPoint : list) {
			if(mapPoint.getMlWhichstop() == stationSequence){
				return mapPoint;
			}
		}
		return null;
	}
	
	
	
	
	/**
	 * 根据gps坐标获取线路上最近的线路点(获取该点前后位置的点，最多3个点，最少2个点)
	 * @param lineUuid
	 * @param lineType
	 * @param latitude
	 * @param longitude
	 * @param stationSeq
	 * @return
	 */
	public List<BusLineMapPoint> getNearstPoints(List<BusLineMapPoint> lineMapPoints, String latitude, String longitude, Integer stationSeq){
		// 地图最近点数组游标 从0开始
		int nearstPointIndex = -1;
		if(stationSeq != null){
			// 注意该方法有缺陷，见方法说明
			nearstPointIndex = getNearstPointIndex(lineMapPoints, latitude, longitude, stationSeq);	//  根据经纬度，获取最近的站点信息的 list数组的index
		}else{
			nearstPointIndex = getNearstPointIndex(lineMapPoints, latitude, longitude);	//  根据经纬度，获取最近的站点信息的 list数组的index
		}
		List<BusLineMapPoint> nearPoints = new ArrayList<BusLineMapPoint>();
		
		if(nearstPointIndex < 0){
			return nearPoints;
		}
		return getNearstPoints(lineMapPoints, nearstPointIndex);
	}
	
	/**
	 * 根据最近的站点信息的 list数组的index，获取该点前后位置的点，最多3个点，最少2个点
	 * @param lineMapPoints
	 * @param nearstPointIndex
	 * @return
	 */
	private List<BusLineMapPoint> getNearstPoints(List<BusLineMapPoint> lineMapPoints, int nearstPointIndex) {
		List<BusLineMapPoint> nearPoints = new ArrayList<BusLineMapPoint>();
		try {
			if (lineMapPoints.size() > 0) {
				// 前一个点
				if (nearstPointIndex > 0) {
					nearPoints.add(lineMapPoints.get(nearstPointIndex - 1));
				}

				if (lineMapPoints.size() < nearstPointIndex) {
					logger.debug("找不到最近的站点");
				}
				// 当前点
				nearPoints.add(lineMapPoints.get(nearstPointIndex));

				// 后一个点
				if (nearstPointIndex < lineMapPoints.size() - 1) {
					nearPoints.add(lineMapPoints.get(nearstPointIndex + 1));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return nearPoints;
	}
	
	/**
	 * 获取GPS点在线路地图上映射最近的点的线路地图数据index值 <br>
	 * 【注意该方法有个缺陷】1、必须确保 数据库存储站点数与报站文件一致；2、如果是原地报站（即不是实际站点gps信息），可能会出错（直线图上来回跳）
	 * 
	 * @param busLineMapPoints
	 *            线路地图点信息
	 * @param lat
	 * @param lng
	 * @param lineStationSeq
	 *            站点序号
	 * @return
	 */
	private int getNearstPointIndex(List<BusLineMapPoint> busLineMapPoints, String lat, String lng, Integer lineStationSeq) {

		/* ************* 根据站序辅助计算 最近地图位置点 start *********************************/
		List<BusLineMapPoint> mapPointList = null;
		if(lineStationSeq != null){
			// 【相对距离辅助方法计算】
			// 【注意该方法有个缺陷】1、必须确保 数据库存储站点数与报站文件一致；2、如果是原地报站（即不是实际站点gps信息），可能会出错（直线图上来回跳）
			mapPointList = getBusLineMapPointByStationSeq(busLineMapPoints, lineStationSeq);
		}else{
			mapPointList = busLineMapPoints;
		}
		/* ************* 根据站序辅助计算 最近地图位置点    end  *********************************/
		
		return getNearstPointIndex(mapPointList, lat, lng); // 实际游标
	}
	
	/**
	 *  获取GPS点在线路地图上映射最近的点的线路地图数据index值
	 * @param points	线路地图点信息
	 * @param lat
	 * @param lng
	 * @return
	 */
	private int getNearstPointIndex(List<BusLineMapPoint> points, String lat, String lng) {
		double dis = Double.MAX_VALUE;
		int index = -1;
		
		for (int i = 0; i < points.size(); i++) {
			BusLineMapPoint ml = points.get(i);
			double d = GpsUtils.getDistance(ml.getMlLat(), ml.getMlLng(), lat, lng);
			if (d < dis) {
				dis = d;
				index = ml.getMlSequence(); // 数据库
			}
		}
		return index -1 ; // 实际游标
	}
	
	public BusLineMapPoint getNearstPoint(List<BusLineMapPoint> points, String lat, String lng) {
		double dis = Double.MAX_VALUE;
		int index = -1;
		BusLineMapPoint rt = null;
		for (int i = 0; i < points.size(); i++) {
			BusLineMapPoint ml = points.get(i);
			double d = GpsUtils.getDistance(ml.getMlLat(), ml.getMlLng(), lat, lng);
			if (d < dis) {
				dis = d;
				index = ml.getMlSequence(); // 数据库
				rt = ml;
			}
		}
		return rt;
	}
	
	/**
	 * 【相对距离辅助方法计算】根据站序，获取地图线上 当前站点 前、后站 间的地图点
	 * @param busLineMapPoints
	 * @param currentStatSeq
	 * @return
	 */
	private List<BusLineMapPoint> getBusLineMapPointByStationSeq(List<BusLineMapPoint> busLineMapPoints, Integer currentStatSeq){
		boolean isLastSeq = false;
		
		int lastSeq = 0;
		for (int j = busLineMapPoints.size()-1; j >=0; j--) {
			BusLineMapPoint mapPoint = busLineMapPoints.get(j);
			if(mapPoint.getMlWhichstop() > 0){
				lastSeq = mapPoint.getMlWhichstop();
				break;
			}
		}
		
		if(lastSeq == currentStatSeq){
			isLastSeq = true;
		}
		
		List<BusLineMapPoint> subMapPoints = null;
		if (currentStatSeq == 1) {
			// 第一站，取第一站和第二站间的所有点
			subMapPoints = busLineMapPoints.subList(0, getMapPointIndexByStationSeq(busLineMapPoints, 2));
		} else if (isLastSeq) {
			// 最后一站、取前一站和当前站的所有点
			int befortStationIndex = getMapPointIndexByStationSeq(busLineMapPoints, currentStatSeq - 1);
			subMapPoints = busLineMapPoints.subList(befortStationIndex, busLineMapPoints.size());
		} else {
			// 中间站，取前一站和后一站间的所有点
			int befortStationIndex = getMapPointIndexByStationSeq(busLineMapPoints, currentStatSeq - 1);
			int afterStationIndex = getMapPointIndexByStationSeq(busLineMapPoints, currentStatSeq + 1);
			subMapPoints = busLineMapPoints.subList(befortStationIndex, afterStationIndex+1);
		}
		
//		for (MapPoint mapPoint : subMapPoints) {
//			if(mapPoint.getMlWhichstop() == currentStatSeq){
//				System.out.println(mapPoint.getMlLineType() + "\t " + mapPoint.getMlSequence() + "\t【" + mapPoint.getMlWhichstop()+ " 】");
//			}else{
//				System.out.println(mapPoint.getMlLineType() + "\t " + mapPoint.getMlSequence() + "\t" + mapPoint.getMlWhichstop());
//				
//			}
//		}
		return subMapPoints;
	}
	
	/**
	 * 【相对距离辅助方法计算】获取站点在当前线路地图点的数组位置
	 * @param allPoints	当前线路所有地图位置
	 * @param stationSeq 站点序号
	 * @return
	 */
	private int getMapPointIndexByStationSeq(List<BusLineMapPoint> allPoints, int stationSeq){
		
		int size = allPoints.size();
		int index = 0;
		for (int i = 0; i < size; i++) {
			BusLineMapPoint mapPoint = allPoints.get(i);
			
			if(mapPoint.getMlWhichstop() == stationSeq){
				
//				System.out.println("找到站点:" + stationSeq);
				index = i;
//				index = mapPoint.getMlSequence();
				break;
			}
		}
		
		return index;
	}
	
}
